package pers.cj.pdos.utils;

import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import pers.cj.pdos.entity.Goods;
import pers.cj.pdos.entity.GoodsStock;
import pers.cj.pdos.entity.Packet;
import pers.cj.pdos.service.IGoodsService;
import pers.cj.pdos.service.IGoodsStockService;
import pers.cj.pdos.service.IPacketService;
import pers.cj.pdos.vo.PacketGoodsVo;
import pers.cj.pdos.vo.PacketVo;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GoodsUtil {
    private String houseId;
    private List goodsList;
    private List packetList;

    private BigDecimal totalAmount = new BigDecimal(0);

    private Map<String,BigDecimal> orderGoodsStockMap = new HashMap<>();//订单中的商品库存
    private Map<String,BigDecimal> orderPacketStockMap = new HashMap<>();//订单中的套餐库存
    private Map<String,BigDecimal> packetGoodsNumberMap = new HashMap<>();//统计订单中套餐的商品的数量的map， 其中数量为基本单位数量
    private Map<String,BigDecimal> allGoodsNumberMap = new HashMap<>();//订单中套餐的商品和商品的总map


    private Map<String,BigDecimal> packet_number_map = new HashMap<>();//订单中套餐的个数（因为订单中可能有相同的套餐占N行,此map将他们进行统计）
    private Map<String,BigDecimal> goods_number_map = new HashMap<>();//订单中套餐的商品个数(基本单位个数)（因为订单中可能有相同的商品占N行，此map将他们进行统计）


    private IGoodsStockService goodsStockService;
    private IGoodsService goodsService;
    private IPacketService packetService;

    public GoodsUtil(String houseId, List goodsList) {
        newEntity(houseId,goodsList,null);
    }

    public GoodsUtil(String houseId, List goodsList, List packetList) {
        newEntity(houseId, goodsList, packetList);
    }

    private void newEntity(String houseId, List goodsList, List packetList){
        WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
        goodsStockService = (IGoodsStockService)context.getBean("goodsStockServiceImpl");
        goodsService = (IGoodsService)context.getBean("goodsServiceImpl");
        packetService = (IPacketService)context.getBean("packetServiceImpl");

        this.houseId = houseId;
        this.goodsList = goodsList;
        this.packetList = packetList;
        init();
    }


    public Map<String, BigDecimal> getAllGoodsNumberMap() {
        return allGoodsNumberMap;
    }

    public BigDecimal getTotalAmount() {
        return totalAmount;
    }

    /**
     * 检查库存
     * @return null 表示检查成功， 其他表示检查库存出现错误
     */
    public String checkStock() {
        for (Map map : goodsStockService.listByHouseAndGoodsMap(houseId, allGoodsNumberMap)) {
            orderGoodsStockMap.put((String)map.get("goods_id"), (BigDecimal)map.get("num"));
        }

        if (!Utils.isEmpty(packetList)){
            for (int i=0;i<packetList.size();i++) {
                Object packet = packetList.get(i);
                String packetId = (String) ReflectionUtils.getFieldValue(packet, "packetId");
                orderPacketStockMap.put(packetId, genPacketStock(packet));
            }
        }


        String msg = null;

        //先比较套餐
        for (Map.Entry<String,BigDecimal> entry : packet_number_map.entrySet()) {
            String packetId = entry.getKey();
            BigDecimal number = entry.getValue();
            if (number.compareTo(new BigDecimal("0")) == 0) {
                Packet packet = packetService.getById(packetId);
                msg = "套餐<"+packet.getName()+">数量不能为0";
                break;
            }

            if (!orderPacketStockMap.containsKey(packetId)){
                Packet packet = packetService.getById(packetId);
                msg = ("套餐<"+packet.getName()+">库存不足");
                break;
            }

            BigDecimal stockNum = orderPacketStockMap.get(packetId);//该套餐对应的库存
            if (stockNum.compareTo(number) == -1){
                //库存小于套餐数量
                Packet packet = packetService.getById(packetId);
                msg = ("套餐<"+packet.getName()+">库存不足");
                break;
            }
        }

        if (!Utils.isEmpty(msg)) {
            return msg;
        }

        //在比较商品
        for (Map.Entry<String,BigDecimal> entry : goods_number_map.entrySet()) {
            String goodsId = entry.getKey();
            BigDecimal number = entry.getValue();
            if (number.compareTo(new BigDecimal("0")) == 0) {
                Goods goods = goodsService.getById(goodsId);
                msg = "商品<"+goods.getName()+">数量不能为0";
                break;
            }

            //商品，比较库存的话，需要结合套餐里面已经使用了该商品的库存
            if (!orderGoodsStockMap.containsKey(goodsId)){
                Goods goods = goodsService.getById(goodsId);
                msg = ("商品<"+goods.getName()+">库存不足");
                break;
            }

            BigDecimal stockNum = orderGoodsStockMap.get(goodsId);//该商品对应的库存

            if (packetGoodsNumberMap.containsKey(goodsId)){
                //套餐中含有该商品，需要累加上套餐中该商品的基本数量
                number = number.add(packetGoodsNumberMap.get(goodsId));
            }
            if (number.compareTo(stockNum) == 1){
                Goods goods = goodsService.getById(goodsId);
                msg = ("商品<"+goods.getName()+">库存不足");
                break;
            }
        }

        return msg;
    }



    private void init() {
        totalAmount = new BigDecimal(0);

        if (!Utils.isEmpty(packetList)){
            //先获取套餐中的商品
            for (int i=0;i<packetList.size();i++){
                Object packet = packetList.get(i);
                String packetId = (String) ReflectionUtils.getFieldValue(packet,"packetId");
                BigDecimal packetNumber = (BigDecimal) ReflectionUtils.getFieldValue(packet,"number");
                BigDecimal amount = (BigDecimal) ReflectionUtils.getFieldValue(packet,"amount");
                if (amount != null) {
                    totalAmount = totalAmount.add(amount);
                }

                //套餐个数map
                if (!packet_number_map.containsKey(packetId)) {
                    //不存在则添加
                    packet_number_map.put(packetId, packetNumber);
                } else {
                    packet_number_map.put(packetId, packet_number_map.get(packetId).add(packetNumber));
                }


                List packetGoodsVoList = (List) ReflectionUtils.getFieldValue(packet,"packetGoodsVoList");
                for (int j=0;j<packetGoodsVoList.size();j++){
                    Object packetGoods = packetGoodsVoList.get(j);
                    String goodsId = (String) ReflectionUtils.getFieldValue(packetGoods,"goodsId");
                    BigDecimal number = (BigDecimal) ReflectionUtils.getFieldValue(packetGoods,"number");
                    BigDecimal times = (BigDecimal) ReflectionUtils.getFieldValue(packetGoods,"times");

                    BigDecimal goodsNumber = packetNumber.multiply(times).multiply(number);

                    //套餐中商品的数量map
                    if (!packetGoodsNumberMap.containsKey(goodsId)) {
                        //不存在则添加
                        packetGoodsNumberMap.put(goodsId, goodsNumber);
                    } else {
                        packetGoodsNumberMap.put(goodsId, packetGoodsNumberMap.get(goodsId).add(goodsNumber));
                    }

                    //所有商品数量map
                    if (!allGoodsNumberMap.containsKey(goodsId)) {
                        //不存在则添加
                        allGoodsNumberMap.put(goodsId, goodsNumber);
                    } else {
                        allGoodsNumberMap.put(goodsId, allGoodsNumberMap.get(goodsId).add(goodsNumber));
                    }
                }
            }
        }

        if (!Utils.isEmpty(goodsList)) {
            //先获取套餐中的商品
            for (int i = 0; i < goodsList.size(); i++) {
                Object goods = goodsList.get(i);
                String goodsId = (String) ReflectionUtils.getFieldValue(goods,"goodsId");
                BigDecimal number = (BigDecimal) ReflectionUtils.getFieldValue(goods,"number");
                BigDecimal times = (BigDecimal) ReflectionUtils.getFieldValue(goods,"times");
                BigDecimal goodsNumber = times.multiply(number);


                BigDecimal amount = (BigDecimal) ReflectionUtils.getFieldValue(goods,"amount");
                if (amount != null) {
                    totalAmount = totalAmount.add(amount);
                }

                //所有商品数量map
                if (!goods_number_map.containsKey(goodsId)) {
                    //不存在则添加
                    goods_number_map.put(goodsId, goodsNumber);
                } else {
                    goods_number_map.put(goodsId, goods_number_map.get(goodsId).add(goodsNumber));
                }

                //所有商品数量map
                if (!allGoodsNumberMap.containsKey(goodsId)) {
                    //不存在则添加
                    allGoodsNumberMap.put(goodsId, goodsNumber);
                } else {
                    allGoodsNumberMap.put(goodsId, allGoodsNumberMap.get(goodsId).add(goodsNumber));
                }
            }
        }
    }

    /**
     * 获取套餐的库存
     * @return
     */
    private BigDecimal genPacketStock(Object packet) {
        BigDecimal packetStock = null;
        List packetGoodsVoList = (List) ReflectionUtils.getFieldValue(packet,"packetGoodsVoList");

        for (int i=0;i<packetGoodsVoList.size();i++) {
            Object packetGoods = packetGoodsVoList.get(i);
            String goodsId = (String) ReflectionUtils.getFieldValue(packetGoods, "goodsId");
            BigDecimal number = (BigDecimal) ReflectionUtils.getFieldValue(packetGoods, "number");
            BigDecimal times = (BigDecimal) ReflectionUtils.getFieldValue(packetGoods, "times");

            if (!orderGoodsStockMap.containsKey(goodsId)) {
                packetStock = new BigDecimal(0);
                break;
            }

            BigDecimal stockNum = orderGoodsStockMap.get(goodsId);

            BigDecimal temp = new BigDecimal(stockNum.divide(number.multiply(times)).intValue());
            if (packetStock==null || (packetStock!=null && packetStock.compareTo(temp)==1)){
                packetStock = temp;
            }

        }

        return packetStock;
    }
}
